#include "app_device.h"

#define BUFFER_SIZE 1024 // 缓冲区大小
#define DEVICE_NUM 10 // 设备最大数量
static Buffer *upBuffer; // 上行缓冲区
static Buffer *downBuffer; // 下行缓冲区
static pthread_t read_thread; // 读线程
static uint8_t device_ids[DEVICE_NUM]; // 设备ID列表
static uint8_t device_length = 0; // 设备数量

int app_device_init(char *filename)
{
    // 初始化设备
    app_mqtt_init();
    upBuffer = app_buffer_init(BUFFER_SIZE);
    downBuffer = app_buffer_init(BUFFER_SIZE);
    pthread_pool_init(5);
    app_modbus_init(filename);
    return 0;
}

void app_device_close(void)
{
    app_mqtt_close();
    app_buffer_free(upBuffer);
    app_buffer_free(downBuffer);
    pthread_pool_destroy();
    app_modbus_close();
    pthread_cancel(read_thread);
    pthread_join(read_thread, NULL);
}
/**
 * @brief 设备ID添加到设备列表中
 * 
 * @param device_id 设备ID
 */
void add_device(uint8_t device_id)
{
    // 遍历设备列表, 如果存在则返回
    for (size_t i = 0; i < device_length; i++)
    {
        if (device_ids[i] == device_id)
        {
            return;
        }
    }
    // 添加设备ID
    device_ids[device_length++] = device_id;
    // 展示设备列表
    printf("设备列表:");
    for (size_t i = 0; i < device_length; i++)
    {
        printf("%d ", device_ids[i]);
    }
    printf("\n");
}
/**
 * 发送数据任务
 */
int task_down_data(void *arg)
{
    // 提取出关键数据
    char dataBuffer[128];
    int len = app_buffer_read(downBuffer, dataBuffer, sizeof(dataBuffer));
    uint16_t data[4];
    uint8_t device_id = dataBuffer[0];
    memcpy(data, &dataBuffer[1], len - 1);
    // 写多个保持寄存器
    app_modbus_writeHoldRegs(device_id, 0, (len - 1) / 2, data);
    // 将设备ID添加到设备列表中
    add_device(device_id);
    return 0;
}
/**
 * 将上游的数据发送给下游设备的回调函数
 */
int down_callback(char *json)
{
    log_debug("接收到下行数据: %s", json);
    // 将json数据转换成字节数组
    char data[128];
    int len = app_message_jsonToBytes(json, data, 128);
    if (len < 0)
    {
        log_error("转换json数据为字节数组失败");
        return -1;
    }
    // 写入下行缓冲区
    int status = app_buffer_write(downBuffer, data, len);
    if (status < 0)
    {
        log_error("写入下行缓冲区失败");
        return -1;
    }
    // 发送数据
    // 注册任务到消息队列，通过线程池线程读取一个消息，通过modbus发送数据
    pthread_pool_registerTask(task_down_data, NULL);
    return 0;
}
/**
 * 移除设备ID
 * 
 * @param device_id 设备ID
 */
void remove_device(uint8_t device_id)
{
    // 遍历设备列表, 如果存在则删除
    for (size_t i = 0; i < device_length; i++)
    {
        if (device_ids[i] == device_id)
        {
            memmove(&device_ids[i], &device_ids[i + 1], (device_length - i - 1) * sizeof(uint8_t));
            device_length--;
        }
    }
    // 展示设备列表
    printf("移除后设备列表:");
    for (size_t i = 0; i < device_length; i++)
    {
        printf("%d ", device_ids[i]);
    }
    printf("\n");
}
/**
 * 上行数据任务
 */
int task_up_data(void *arg)
{
    // 读取上行缓冲区的数据
    char data[128];
    int len = app_buffer_read(upBuffer, data, sizeof(data));
    if(len == -1)
    {
        log_error("读取上行缓冲区数据失败");
        return -1;
    }
    // 创建json数据
    char *json = app_message_bytesToJson(data, len);
    // 发送数据
    app_mqtt_send(json);
    // 移除设备ID
    uint8_t device_id = data[0];
    uint8_t motor_status = data[5];
    if(motor_status == 0)
    {
        remove_device(device_id);
    }
    return 0;
}
// 接收所有下游设备的上行数据
void *up_recv(void *arg)
{
    // 读上行缓冲区的数据
    while (1)
    {
        // 遍历设备列表
        for (size_t i = 0; i < device_length; i++)
        {
            // 读取多个输入寄存器
            uint8_t device_id = device_ids[i];
            uint16_t data_input[3];
            int status = app_modbus_readInputregs(device_id, 0, 3, data_input);
            log_debug("data_input = %x, %x, %x", data_input[0], data_input[1], data_input[2]);
            if(status == -1)
            {
                log_error("读取多个输入寄存器失败");
                return NULL;
            }
            // 整合数据
            char device_data[7];
            memcpy(device_data, &device_id, 1);
            memcpy(&device_data[1], data_input, 6);
            // 将数据写到上行缓冲区
            app_buffer_write(upBuffer, device_data, sizeof(device_data));
            // 将后续任务交给线程执行
            pthread_pool_registerTask(task_up_data, NULL);
            // 两个设备间隔1秒
            sleep(1);
        }
    }
    return NULL;
}

void app_device_start(void)
{
    // 注册接收下行数据的回调函数
    app_mqtt_registerRecvCallback(down_callback);
    // 创建线程函数不断接收所有下游设备的上行数据
    pthread_create(&read_thread, NULL, up_recv, NULL);
}
